/**
 * Created by chenyong on 2015/7/23.
 */

var krpanoplugin = function()
{
    var local = this;
    var krpano = null;
    var plugin = null;

    var plugincanvascontext = null;

    //krpano函数重载 注册
    local.registerplugin = function(krpanointerface, pluginpath, pluginobject)
    {
        krpano = krpanointerface;
        plugin = pluginobject;
        initplugin();
    }

    //krpano函数重载 插件被移除时调用
    local.unloadplugin = function()
    {
        plugin = null;
        krpano = null;
    }

    //krpano函数重载
    local.hittest = function(x,y)
    {
        if (plugincanvascontext)
        {
            return plugincanvascontext.isPointInPath(x,y);
        }
        return false;
    }

    //krpano函数重载
    local.onresize = function(width,height)
    {
        return false;
    }

    //调试
    function debug(str)
    {
        if(plugin.debug == "true"){
            krpano.call("showlog(true);");
            krpano.set("debugmode", true);
            krpano.trace(0,str);
        }
    }

    /*
     * 私有变量
     */
    var objTagStageValues = new Object();
    var objTagDefaults = new Object();
    var objTagPoints = new Object();
    var objTagStagePoints = new Array();
    var objLastTagReq = new Object();
    var boolGetTags_timeout = new Boolean(false);
    var boolShowTagsOnLoad = new Boolean(true);
    var boolPauseLoading = false;

    //插件初始化
    function initplugin()
    {
        var no_errors = true;
        if(plugin.tagpointsurl == undefined){     //plugin.tagpointsurl==http://srv.chingkun.com/api/panos/zhaofans-midi/tags?limit=40
            no_errors = false;
        }

        if(plugin.tagdefaultsurl == undefined){    //plugin.tagdefaultsurl ==http://srv.chingkun.com/api/panos/zhaofans-midi/tagdefaults
            no_errors = false;
        }

        if(no_errors)
        {
            plugin.hidetags = hidetags;
            plugin.showtags = showtags;
            plugin.gettags = gettags;

            plugin.start = start;

            plugin.removetag = removetag;

            plugin.restart = restart;

            plugin.removebyname = removebyname;

            plugin.pause = pause;

            plugin.resume = resume;

            if(plugin.sensitivity == undefined){
                plugin.sensitivity = 5;
            }

            if(plugin.req_period == undefined){
                plugin.req_period = 3000;
            }

            if(plugin.autostart == undefined){
                plugin.autostart = "true";
            }

            if(plugin.persistent == undefined){
                plugin.persistent = "false";
            }

            if(plugin.runonce == undefined){
                plugin.runonce = "false";
            }

            plugin.set_sensitivity = set_sensitivity;
            if(plugin.autostart == "true"){
                start();
            }
            else{
                get_tagdefaults();
                set_sensitivity();
            }
        }
    }

    //读取标注点的默认值
    function get_tagdefaults()
    {
        var url = krpano.parsePath(plugin.tagdefaultsurl);
        jQuery.getJSON(url).done(function(data) {
            objTagDefaults = data;
        });
    }

    //设置标注点默认值
    function set_tagdefault(prop, value){
        objTagDefaults[prop] = value;
    }

    //隐藏标注点
    function hidetags()
    {
        var strPanoCall = new String("");
        set_tagdefault("alpha", "0");
        set_tagdefault("enabled", "false");
        boolShowTagsOnLoad = false;
        pause();
        for (var tag in objTagStagePoints){
            strPanoCall += "tween(hotspot[" + objTagStagePoints[tag].name + "].alpha, 0 ,1, default, set(hotspot[" + objTagStagePoints[tag].name + "].enabled, false));";
        }
        krpano.call(strPanoCall);
    }

    //显示标注点
    function showtags()
    {
        var strPanoCall = new String("");
        set_tagdefault("alpha", "0");
        set_tagdefault("enabled", "true");
        boolShowTagsOnLoad = true;
        resume();
        for (var tag in objTagStagePoints){
            strPanoCall += "set(hotspot[" + objTagStagePoints[tag].name + "].enabled, true);";
            strPanoCall += "tween(hotspot[" + objTagStagePoints[tag].name + "].alpha, 1 ,1);";
        }
        krpano.call(strPanoCall);
    }

    function gettags(onloaded)
    {
        get_tags(onloaded);
    }

    function start()
    {
        krpano.set("events.onnewpano", startplugin());
    }

    function startplugin()
    {
        get_tagdefaults();
        set_sensitivity();
        if(plugin.runonce == "false"){
            krpano.set("events.onviewchange", sensitivity);
        }
        else{
            //gettags();
            krpano.set("events.onloadcomplete", gettags);
        }
    }

    function restart()
    {
        debug("plugin[" + plugin.name + "] - restart called");
        var objTagStagePointsFiltered = new Array();
        for (var tag in objTagStagePoints){
            krpano.call("removehotspot(" + objTagStagePoints[tag].name + ")");
        }
        objTagStagePoints = objTagStagePointsFiltered;
        objTagStagePointsFiltered = null;
        get_tags();
    }

    function removebyname(strName)
    {
        var objTagStagePointsFiltered = new Array();
        for (var tag in objTagStagePoints){
            if(strName != objTagStagePoints[tag].name){
                objTagStagePointsFiltered.push(objTagStagePoints[tag]);
            }
            else{
                krpano.call("removehotspot(" + objTagStagePoints[tag].name + ")");
            }
        }
        objTagStagePoints = objTagStagePointsFiltered;
        objTagStagePointsFiltered = null;
    }

    function pause()
    {
        boolPauseLoading = true;
    }

    function resume()
    {
        boolPauseLoading = false;
    }

    function set_sensitivity()
    {
        objLastTagReq.sensitivity = plugin.sensitivity;
        var view = krpano.get("view");
        objLastTagReq.atv = view.vlookat;
        objLastTagReq.ath = view.hlookat;
        objLastTagReq.fov = view.fov;
        objLastTagReq.fovfactor = 0;
        objLastTagReq.time = 0;
    }

    function sensitivity()
    {
        var timeNow = new Date().getTime();
        if (timeNow < objLastTagReq.time + plugin.req_period){
            return;
        }

        var fovfactor;
        var factor = 10 * (objLastTagReq.sensitivity / 5);

        if(krpano.view.fov >= 120){
            fovfactor = 1.5;
        }else if(krpano.view.fov >= 90){
            fovfactor = 1.3;
        }else if(krpano.view.fov >= 60){
            fovfactor = 1.1;
        }else if(krpano.view.fov >= 30){
            fovfactor = 0.9;
        }else if(krpano.view.fov >= 20){
            fovfactor = 0.9;
        }else if(krpano.view.fov >= 10){
            fovfactor = 0.7;
        }else if(krpano.view.fov >= 5){
            fovfactor = 0.5;
        }else if(krpano.view.fov < 5){
            fovfactor = 0.3;
        }

        var atvdiff = objLastTagReq.atv - krpano.view.vlookat;
        if(atvdiff < 0){
            atvdiff = atvdiff * -1;
        }

        var athdiff = objLastTagReq.ath - krpano.view.hlookat;
        if(athdiff < 0){
            athdiff = athdiff * -1;
        }

        if((atvdiff > (factor * fovfactor) || athdiff > (factor * fovfactor) || fovfactor != objLastTagReq.fovfactor) /*&& boolGetTags_timeout */&& boolPauseLoading === false)
        {
            boolGetTags_timeout = false;

            objLastTagReq.atv = krpano.view.vlookat;
            objLastTagReq.ath = krpano.view.hlookat;
            objLastTagReq.fovfactor = fovfactor;
            objLastTagReq.time = new Date().getTime();
            get_tags();
        }
    }


    function get_tags(onloadedaction)
    {
        calc_visible_stage();
        var url = krpano.parsePath(plugin.tagpointsurl);
        var index = plugin.tagpointsurl.indexOf("?");
        if(index == -1){
            url += '?';
        }else{
            url += '&';
        }

        url += "fov=" + objTagStageValues.fov + '&' + 'atv_min=' + objTagStageValues.atv_min + '&' + 'ath_min=' + objTagStageValues.ath_min + '&' + 'atv_max=' + objTagStageValues.atv_max + '&' + 'ath_max=' + objTagStageValues.ath_max;

        jQuery.getJSON(url).done(function(data) {
            objTagPoints = data;
            if(plugin.persistent == "false"){
                remove_tags();
            }
            for (var tag in objTagPoints){
                create_tag(objTagPoints[tag]);
            }
            objTagPoints = null;

            if (typeof onloadedaction != 'undefined'){
                krpano.call(onloadedaction);
            }
        });
    }

    function removetag(name){
        if (plugin.persistent != "false"){
            name = "pers_"+name;
        }
        for (var tag in objTagStagePoints){
            if (objTagStagePoints[tag].name == name){
                // notify that we are removing
                if ( plugin.ontagremove !== undefined){
                    var actioncall = plugin.ontagremove.replace("{name}", objTagStagePoints[tag].name );
                    krpano.call(actioncall);
                }
                krpano.call("removehotspot(" + objTagStagePoints[tag].name + ");");
                delete objTagStagePoints[tag];
            }
        }
    }

    function remove_tags()
    {
        var objTagStagePointsFiltered = new Array();
        for (var tag in objTagStagePoints){
            var onstage_atv = false;
            var onstage_ath = false;

            //atv
            if(objTagStageValues.atv_min < objTagStageValues.atv_max){
                if((objTagStagePoints[tag].atv > objTagStageValues.atv_min) && (objTagStagePoints[tag].atv < objTagStageValues.atv_max)){
                    onstage_atv = true;
                }
            }
            if(objTagStageValues.atv_min > objTagStageValues.atv_max){
                if((objTagStagePoints[tag].atv > objTagStageValues.atv_min) || (objTagStagePoints[tag].atv < objTagStageValues.atv_max)){
                    onstage_atv = true;
                }
            }

            //ath
            if(objTagStageValues.ath_min < objTagStageValues.ath_max){
                if((objTagStagePoints[tag].ath > objTagStageValues.ath_min) && (objTagStagePoints[tag].ath < objTagStageValues.ath_max)){
                    onstage_ath = true;
                }
            }
            if(objTagStageValues.ath_min > objTagStageValues.ath_max){
                if((objTagStagePoints[tag].ath > objTagStageValues.ath_min) || (objTagStagePoints[tag].ath < objTagStageValues.ath_max)){
                    onstage_ath = true;
                }
            }

            if(onstage_atv && onstage_ath){
                objTagStagePointsFiltered.push(objTagStagePoints[tag]);
            }
            else {
                if ( plugin.ontagremove !== undefined){
                    var actioncall = plugin.ontagremove.replace("{name}", objTagStagePoints[tag].name );
                    krpano.call(actioncall);
                }
                krpano.call("removehotspot(" + objTagStagePoints[tag].name + ");");
            }
        }
        objTagStagePoints = objTagStagePointsFiltered;
        objTagStagePointsFiltered = null;
    }

    function create_tag(objTag)
    {
        var strCreateTagCall = new String("");
        var objTagBase = new Object();
        var tagIsOnStage = new Boolean(false);

        for (var val0 in objTagDefaults){
            objTagBase[val0] = objTagDefaults[val0];
        }
        for (var val1 in objTag){
            objTagBase[val1] = objTag[val1];
        }
        if(objTagBase.name == undefined){
            objTagBase.name = "tag_" + Math.floor(Math.random() * 1000000) + "_" + Math.floor(Math.random() * 1000000);
        }
        for (var tag in objTagStagePoints){
            if(objTagStagePoints[tag].name == objTagBase.name){
                tagIsOnStage = true;
            }
        }
        if(tagIsOnStage == false){
            objTagStagePoints.push(objTagBase);
            strCreateTagCall += 'removehotspot(' + objTagBase.name + '); addhotspot(' + objTagBase.name + ');';
        }

        for (var val2 in objTagBase){
            if(val2 == 'alpha' && boolShowTagsOnLoad == true){
                if(tagIsOnStage == false){
                    strCreateTagCall += 'set(hotspot[' + objTagBase.name + '].alpha, 0);';
                }else{
                    strCreateTagCall += 'set(hotspot[' + objTagBase.name + '].alpha, 1);';
                }
            }
            else if (val2 == 'fov'){
                strCreateTagCall += 'set(hotspot[' + objTagBase.name + '].scale,'+ objTagBase[val2]/90.0+');';
            }
            else{
                strCreateTagCall += 'set(hotspot[' + objTagBase.name + '].' + val2 + ', ' + objTagBase[val2] + ');';
            }
        }

        if(boolShowTagsOnLoad == true && tagIsOnStage == false){
            strCreateTagCall += "tween(hotspot[" + objTagBase.name + "].alpha, 1 ,1);";
        }

        krpano.call(strCreateTagCall);
        strCreateTagCall = null;
    }

    function signed_h(ath){
        h = ath%360; /* restrict to +-360 */
        if (h<=-180){
            h = 360+h;
        }
        else if(h>180){
            h = 360-h;
        }
        return h;
    }

    //计算全景图的可视区域
    function calc_visible_stage()
    {
        objTagStageValues.width = 0;
        objTagStageValues.width_middle = 0;
        objTagStageValues.height = 0;
        objTagStageValues.height_middle = 0;
        objTagStageValues.atv_min = 0;
        objTagStageValues.ath_min = 0;
        objTagStageValues.atv_max = 0;
        objTagStageValues.ath_max = 0;
        objTagStageValues.fov = 0;

        objTagStageValues.fov = krpano.view.fov;

        objTagStageValues.width = krpano.get("stagewidth");
        objTagStageValues.width_middle = parseInt(objTagStageValues.width) / 2;
        krpano.set("width_middle", objTagStageValues.width_middle);

        objTagStageValues.height = krpano.get("stageheight");
        objTagStageValues.height_middle = parseInt(objTagStageValues.height) / 2;
        krpano.set("height_middle", objTagStageValues.height_middle);

        krpano.call(String("screentosphere(0,height_middle,fc_ath_min,dummy);"));
        objTagStageValues.ath_min = krpano.get('fc_ath_min');

        krpano.call(String("screentosphere(stagewidth,height_middle,fc_ath_max,dummy);"));
        objTagStageValues.ath_max = krpano.get("fc_ath_max");

        krpano.call(String("screentosphere(width_middle,0,dummy,fc_atv_min);"));
        objTagStageValues.atv_min = krpano.get('fc_atv_min');

        krpano.call(String("screentosphere(width_middle,stageheight,dummy,fc_atv_max);"));
        objTagStageValues.atv_max = krpano.get("fc_atv_max");

        fc_hlookat = signed_h(krpano.view.hlookat);

        // calculation bug in screentosphere krpano
        if (objTagStageValues.ath_min < objTagStageValues.ath_max)
        {
            if (objTagStageValues.ath_min>fc_hlookat){
                objTagStageValues.ath_min = signed_h(fc_hlookat - krpano.view.fov/2);
            }
            if (objTagStageValues.ath_max<fc_hlookat){
                objTagStageValues.ath_max = signed_h(krpano.view.hlookat + krpano.view.fov/2);
            }
        }
        else
        {
            if (objTagStageValues.ath_min<fc_hlookat){
                objTagStageValues.ath_min = signed_h(fc_hlookat - krpano.view.fov/2);
            }
            if (objTagStageValues.ath_max>fc_hlookat){
                objTagStageValues.ath_max = signed_h(krpano.view.hlookat + krpano.view.fov/2);
            }
        }
        /* -90 <=> 90 */
        if (objTagStageValues.atv_min>krpano.view.vlookat){
            console.log("atv_min > vlookat, atv_min="+objTagStageValues.atv_min+ " vlookat="+ krpano.view.vlookat +" defaulting to fov/2="+ String(krpano.view.vlookat - krpano.view.fov/2));
            objTagStageValues.atv_min = krpano.view.vlookat - krpano.view.fov/2;
        }
        if (objTagStageValues.atv_max<krpano.view.vlookat){
            objTagStageValues.atv_max = krpano.view.vlookat + krpano.view.fov/2;
        }
    }
};